use crate::utils::get_reader;
use anyhow::Ok;
use base64::{
    prelude::{BASE64_STANDARD_NO_PAD, BASE64_URL_SAFE_NO_PAD},
    Engine,
};

use std::io::Read;

use crate::cli::Base64Format;

#[allow(dead_code)]
pub fn abc(a: i32, b: i32) -> i32 {
    let alphabet = "dasdfaadds";
    println!("{}", alphabet);
    a + b
}

pub fn process_encode(input: &str, format: Base64Format) -> anyhow::Result<String> {
    let mut reader = get_reader(input)?;
    let mut vec = Vec::new();
    reader.read_to_end(&mut vec)?;
    let vec = &vec[0..&vec.len() - 1];
    let vec: Vec<u8> = vec.into();
    let encode = match format {
        Base64Format::Standard => BASE64_STANDARD_NO_PAD.encode(vec),
        Base64Format::UrlSafe => BASE64_URL_SAFE_NO_PAD.encode(vec),
    };
    Ok(encode)
}

pub fn process_decode(input: &str, format: Base64Format) -> anyhow::Result<Vec<u8>> {
    let mut read = get_reader(input)?;
    let mut vec = String::new();
    read.read_to_string(&mut vec)?;
    let decoded = match format {
        Base64Format::Standard => BASE64_STANDARD_NO_PAD.decode(vec.trim())?,
        Base64Format::UrlSafe => BASE64_STANDARD_NO_PAD.decode(vec.trim())?,
    };
    Ok(decoded)
}

#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_encode() {
        let ret = BASE64_STANDARD_NO_PAD.encode("123".as_bytes());
        assert_eq!(ret, "MTIz".to_string())
    }
    #[test]
    fn test_decode() {
        let ret = BASE64_STANDARD_NO_PAD.decode("MTIz".as_bytes()).unwrap();
        assert_eq!(String::from_utf8(ret).unwrap(), "123".to_string())
        //println!("{}", String::from_utf8(ret).unwrap());
    }

    #[test]
    fn test_process_encode_by_standard() {
        process_encode("Cargo.toml", Base64Format::Standard).unwrap();
    }

    #[test]
    fn test_decode_by_standard() {
        let input = "fixtures/cargo_toml.txt";
        let format = Base64Format::Standard;
        let ret = process_decode(input, format).unwrap();
        let ret = String::from_utf8(ret).unwrap();
        println!("ret:{}", ret);
        //assert!();
    }
}
